package com.starblink.search.search.ui.fragment

import androidx.collection.ArrayMap
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.GsonUtils
import com.starblink.android.basic.base.BaseViewModel
import com.starblink.android.basic.config.StorageKeys
import com.starblink.android.basic.network.base.SkGqlClient
import com.starblink.basic.apollo.ext.optional
import com.starblink.basic.route.RoutePage
import com.starblink.basic.storage.SkStorage
import com.starblink.rocketreserver.FetchHotAndShadingWordQuery
import com.starblink.rocketreserver.FetchSearchWordConfigQuery
import com.starblink.rocketreserver.FetchSubscribeMerchantWebRecommendQuery
import com.starblink.rocketreserver.FetchSugWordQuery
import com.starblink.rocketreserver.fragment.MerchantWebVOF
import com.starblink.rocketreserver.fragment.SearchWordVOF
import com.starblink.rocketreserver.type.MerchantWebRecommendReq
import com.starblink.rocketreserver.type.SearchWordConfigRequest
import com.starblink.search.config.SearchConfig
import com.starblink.search.result.ui.fragment.BaseSearchVM
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.lang.Integer.min
import java.util.*
import kotlin.random.Random

internal class SearchHomeFragmentVM : BaseSearchVM() {

    val storeList = arrayListOf<MerchantWebVOF>()

    val storeLD = MutableLiveData<Boolean>()

    val history = LinkedList<String>()

    val historyLD = MutableLiveData<Boolean>()

    val hotwordList = arrayListOf<SearchWordVOF>()

    val hotwordShownList = arrayListOf<SearchWordVOF>()

    val hotwordLD = MutableLiveData<Boolean>()

    var fetchingConfig: Boolean = false

    var scene = RoutePage.Search.SCENE.NORMAL

    var historyTag: String = ""

    val historyDiskKey: String
        get() = historyTag + when (scene) {
            RoutePage.Search.SCENE.GOODS, RoutePage.Search.SCENE.DISCOVER, RoutePage.Search.SCENE.STORES -> "${StorageKeys.SEARCH_HISTORY}_${scene.value}"
            else -> StorageKeys.SEARCH_HISTORY
        }

    fun queryHistory() {
        GsonUtils.fromJson(SkStorage.getString(historyDiskKey, ""), history.javaClass)?.let {
            history.addAll(it)
            historyLD.postValue(history.isNotEmpty())
        }
    }

    fun saveHistory(word: String) {
        history.remove(word)
        history.add(0, word)
        while (history.size >= 15) {
            history.removeLast()
        }
        SkStorage.put(historyDiskKey, GsonUtils.toJson(history))
    }

    fun refreshHistory() {
        historyLD.postValue(true)
    }

    fun clearHistory() {
        history.clear()
        historyLD.postValue(false)
        SkStorage.remove(historyDiskKey)
    }

    fun queryHotWord() {
        viewModelScope.launch {
            val response = SkGqlClient.skQuery(
                FetchHotAndShadingWordQuery()
            )
            val list = response?.data?.fetchHotAndShadingWord?.hotWordList?.mapNotNull { it?.searchWordVOF }
            hotwordList.clear()
            list?.let {
                hotwordList.addAll(it)
            }
            refreshHotWord()
        }
    }

    fun refreshHotWord() {
        if (hotwordList.isEmpty()) {
            return
        }

        hotwordShownList.clear()

        val size = min(6, hotwordList.size)
        val map = ArrayMap<Int, Boolean>()
        val random = Random(System.currentTimeMillis())
        while (hotwordShownList.size < size) {
            val index = random.nextInt(hotwordList.size)
            if (map[index] == true || index >= hotwordList.size) {
                continue
            }
            map[index] = true
            hotwordShownList.add(hotwordList[index])
        }

        hotwordLD.postValue(hotwordShownList.isNotEmpty())
    }

    fun queryRecStore() {
        viewModelScope.launch {
            val response = SkGqlClient.skQuery(
                FetchSubscribeMerchantWebRecommendQuery(
                    merchantParams = MerchantWebRecommendReq(
                        pageNo = 1,
                        pageSize = 6,
                        clientTime = "",
                        sceneCode = 4,
                    )
                )
            )
            val list = response?.data?.fetchSubscribeMerchantWebRecommend?.merchantWebList?.map { it.merchantWebVOF }
            storeList.clear()
            list?.let {
                storeList.addAll(it)
            }
            storeLD.postValue(list?.isNotEmpty() == true)
        }
    }



    var curKeyword: String? = null

    val sugWordList = mutableListOf<FetchSugWordQuery.FetchSugWord>()

    val sugWordsLD = MutableLiveData<Boolean>()

    var textChangeTimeTag = 0L

    var subWordJob: Job? = null

    var requestPreKeyWord: String? = null

    fun fetchSugWords(keyword: String) {
        subWordJob = viewModelScope.launch {
            delay(300L)
            val response = SkGqlClient.skQuery(
                FetchSugWordQuery(
                    searchScene = SearchConfig.SCENE_ALL,
                    keyword = keyword,
                    pageNo = 1.optional(),
                    pageSize = 20.optional(),
                )
            )
            response?.data?.fetchSugWord?.run {
                sugWordList.clear()
                sugWordList.addAll(this)
                sugWordsLD.postValue(this.isNotEmpty())
            }
        }
        if (keyword.length == 1 && (requestPreKeyWord == null || requestPreKeyWord!!.length < keyword.length)) {
            subWordJob = null
        }
    }

    fun fetchSearchWordConfig(
        word: String,
        wordSearchType : Int = SearchConfig.SearchWordSourceConfig.O_TYPE_INPUT,
        call: ((config: FetchSearchWordConfigQuery.FetchSearchWordConfig) -> Unit)? = null
    ) {
        if (fetchingConfig) return
        viewModelScope.launch {
            fetchingConfig = true
            showActivityLoading()
            val config = SkGqlClient.skQuery(
                FetchSearchWordConfigQuery(
                    param = SearchWordConfigRequest(
                        type = wordSearchType,
                        searchWord = word,
                    ).optional()
                ),
                //showDefaultLoading = true,
            )?.data?.fetchSearchWordConfig
            fetchingConfig = false
            if (config != null) {
                call?.invoke(config)
            } else {
                call?.invoke(
                    FetchSearchWordConfigQuery.FetchSearchWordConfig(
                        actualWord = word,
                        jumpType = null,
                        jumpUrl = null,
                        goodsRuleId = null,
                    )
                )
            }
        }
    }

}